package com.qimu.saiyou.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.qimu.saiyou.annotation.AuthCheck;
import com.qimu.saiyou.common.BaseResponse;
import com.qimu.saiyou.common.DeleteRequest;
import com.qimu.saiyou.common.ErrorCode;
import com.qimu.saiyou.common.ResultUtils;
import com.qimu.saiyou.exception.BusinessException;
import com.qimu.saiyou.exception.ThrowUtils;
import com.qimu.saiyou.model.dto.exampaper.ExamPaperAddRequest;
import com.qimu.saiyou.model.dto.exampaper.ExamPaperQueryRequest;
import com.qimu.saiyou.model.dto.exampaper.ExamPaperUpdateRequest;
import com.qimu.saiyou.model.dto.question.PaperQuestionDTO;
import com.qimu.saiyou.model.dto.userpaper.UserPaperQueryRequest;
import com.qimu.saiyou.model.entity.*;
import com.qimu.saiyou.model.enums.QuestionTypeEnum;
import com.qimu.saiyou.model.vo.ExamPaperVO;
import com.qimu.saiyou.model.vo.QuestionAnswerVO;
import com.qimu.saiyou.model.vo.QuestionVO;
import com.qimu.saiyou.model.vo.UserPaperQuestionVo;
import com.qimu.saiyou.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 试卷
 *
 *@author: FeiXiang
 * 
 */
@RestController
@RequestMapping("/examPaper")
@Slf4j
public class ExamPaperController {

    @Resource
    private ExamPaperService examPaperService;
    @Resource
    private CompetitionService competitionService;
    @Resource
    private UserService userService;

    @Resource
    private QuestionService questionService;

    @Resource
    private UserPaperService userPaperService;
    @Resource
    private UserPaperAnswerService userPaperAnswerService;
    // region 增删改查

    /**
     * 创建
     *
     * @param examPaperAddRequest
     * @param request
     * @return
     */
    @PostMapping("/add")
    @AuthCheck(anyRole = {"admin", "teacher"})
    public BaseResponse<Long> addExamPaper(@RequestBody ExamPaperAddRequest examPaperAddRequest, HttpServletRequest request) {
        if (examPaperAddRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        long newExamPaperId = examPaperService.addExamPaper(examPaperAddRequest);
        return ResultUtils.success(newExamPaperId);
    }

    /**
     * 删除
     *
     * @param deleteRequest
     * @param request
     * @return
     */
    @PostMapping("/delete")
    @AuthCheck(anyRole = {"admin", "teacher"})
    public BaseResponse<Boolean> deleteExamPaper(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) {
        if (deleteRequest == null || deleteRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        long id = deleteRequest.getId();
        // 判断是否存在
        ExamPaper oldExamPaper = examPaperService.getById(id);
        ThrowUtils.throwIf(oldExamPaper == null, ErrorCode.NOT_FOUND_ERROR);
        boolean b = examPaperService.deleteExamPaper(id);
        return ResultUtils.success(b);
    }

    /**
     * 更新（仅管理员）
     *
     * @param examPaperUpdateRequest
     * @return
     */
    @PostMapping("/update")
    @AuthCheck(anyRole = {"admin", "teacher"})
    public BaseResponse<Boolean> updateExamPaper(@RequestBody ExamPaperUpdateRequest examPaperUpdateRequest) {
        if (examPaperUpdateRequest == null || examPaperUpdateRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        boolean result = examPaperService.updateExamPaper(examPaperUpdateRequest);
        return ResultUtils.success(result);
    }


    /**
     * 分页获取列表（仅管理员）
     *
     * @param examPaperQueryRequest
     * @return
     */
    @PostMapping("/list/page")
    public BaseResponse<Page<ExamPaper>> listExamPaperByPage(@RequestBody ExamPaperQueryRequest examPaperQueryRequest) {
        long current = examPaperQueryRequest.getCurrent();
        long size = examPaperQueryRequest.getPageSize();
        // 限制爬虫
        Page<ExamPaper> examPaperPage = examPaperService.page(new Page<>(current, size),
                examPaperService.getQueryWrapper(examPaperQueryRequest));
        return ResultUtils.success(examPaperPage);
    }

    /**
     * 分页获取列表（封装类）
     *
     * @param examPaperQueryRequest
     * @param request
     * @return
     */
    @PostMapping("/list/paperAndQuestion/page/vo")
    public BaseResponse<ExamPaperVO> listExamPaperAndQuestionVOByPage(@RequestBody ExamPaperQueryRequest examPaperQueryRequest,
                                                                      HttpServletRequest request) {
        long current = examPaperQueryRequest.getCurrent();
        long size = examPaperQueryRequest.getPageSize();
        String searchText = examPaperQueryRequest.getSearchText();
        Long id = examPaperQueryRequest.getId();
        ExamPaper examPaper = examPaperService.getById(id);
        ThrowUtils.throwIf(examPaper == null, ErrorCode.PARAMS_ERROR, "试卷不存在");
        ExamPaperVO examPaperVO = ExamPaperVO.objToVo(examPaper);
        // 限制爬虫
        MPJLambdaWrapper<Question> wrapper = new MPJLambdaWrapper<Question>()
                .selectAll(Question.class)
                .selectAll(PaperQuestion.class)
                .eq(ObjectUtils.isNotEmpty(examPaper.getId()), PaperQuestion::getPaperId, examPaper.getId())
                .like(StringUtils.isNotBlank(searchText), Question::getContent, searchText)
                .leftJoin(PaperQuestion.class, PaperQuestion::getQuestionId, Question::getId);

        Page<PaperQuestionDTO> questionDTOPage = questionService.selectJoinListPage(new Page<>(current, size), PaperQuestionDTO.class, wrapper);
        examPaperVO.setQuestionList(questionService.getQuestionPaperVOPageByDTO(questionDTOPage).getRecords());
        int sum = questionDTOPage.getRecords().stream().mapToInt(PaperQuestionDTO::getScore).sum();
        examPaperVO.setTotalScore(sum);
        return ResultUtils.success(examPaperVO);
    }

    @PostMapping("/user/paper/vo")
    public BaseResponse<UserPaperQuestionVo> listUserPaperVOByPage(@RequestBody UserPaperQueryRequest userPaperQueryRequest,
                                                                   HttpServletRequest request) {
        if (ObjectUtils.anyNull(userPaperQueryRequest, userPaperQueryRequest.getCompetitionId()) || userPaperQueryRequest.getCompetitionId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Competition competition = competitionService.getById(userPaperQueryRequest.getCompetitionId());
        if (competition == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "赛事不存在");
        }
        User loginUser = userService.getLoginUser(request);
        QueryWrapper<UserPaper> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(UserPaper::getCompetitionId, competition.getId())
                .eq(UserPaper::getUserId, loginUser.getId())
                .eq(UserPaper::getExamId, competition.getExamId());
        UserPaper userPaper = userPaperService.getOne(wrapper);
        return getUserPaperList(userPaper);
    }

    /**
     * 根据 id 获取
     *
     * @param id
     * @return
     */
    @GetMapping("/get/user/paper/status")
    public BaseResponse<Boolean> getUserPaperStatus(long id) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        UserPaper userPaper = userPaperService.getById(id);
        if (userPaper == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "考试不存在");
        }
        String state = userPaper.getState();
        if ("submit".equals(state) || "finish".equals(state)) {
            return ResultUtils.success(false);
        }
        return ResultUtils.success(true);
    }

    @PostMapping("/user/paper/vo/byId")
    public BaseResponse<UserPaperQuestionVo> listUserPaperVOById(long id, HttpServletRequest request) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        UserPaper userPaper = userPaperService.getById(id);
        return getUserPaperList(userPaper);
    }

    @NotNull
    private BaseResponse<UserPaperQuestionVo> getUserPaperList(UserPaper userPaper) {
        ThrowUtils.throwIf(userPaper == null, ErrorCode.NOT_FOUND_ERROR, "考试不存在");
        String state = userPaper.getState();
        ThrowUtils.throwIf("finish".equals(state), ErrorCode.NOT_FOUND_ERROR, "考试已结束");
        ThrowUtils.throwIf("submit".equals(state), ErrorCode.NOT_FOUND_ERROR, "考试已提交");

        List<UserPaperAnswer> userPaperAnswers = userPaperAnswerService.lambdaQuery()
                .eq(UserPaperAnswer::getUserPaperId, userPaper.getId())
                .list();
        List<Long> userPaperQuestionIdList = userPaperAnswers.stream().map(UserPaperAnswer::getQuestionId).collect(Collectors.toList());
        List<Question> questions = questionService.listByIds(userPaperQuestionIdList);
        Page<Question> questionPage = new Page<>();
        questionPage.setRecords(questions);
        Page<QuestionVO> questionNoRightVOPage = questionService.getQuestionNoRightVOPage(questionPage);
        List<QuestionVO> records = questionNoRightVOPage.getRecords();
        List<QuestionVO> questionVOArrayList = new ArrayList<>();
        disruptionQuestion(records, questionVOArrayList);
        UserPaperQuestionVo userPaperQuestionVo = new UserPaperQuestionVo();
        BeanUtils.copyProperties(userPaper, userPaperQuestionVo);
        userPaperQuestionVo.setQuestionList(questionVOArrayList);

        List<QuestionVO> collect = userPaperQuestionVo.getQuestionList().stream().peek(questionVO -> {
            List<QuestionAnswerVO> questionAnswerList = questionVO.getQuestionAnswerList();
            List<UserPaperAnswer> userAnswers = userPaperAnswers.stream().filter(a -> a.getQuestionId().equals(questionVO.getId())).collect(Collectors.toList());
            for (QuestionAnswerVO questionAnswerVO : questionAnswerList) {
                for (UserPaperAnswer userAnswer : userAnswers) {
                    if (questionAnswerVO.getId().equals(userAnswer.getAnswerId())) {
                        questionAnswerVO.setSelect(true);
                    }
                }
            }
        }).collect(Collectors.toList());
        userPaperQuestionVo.setQuestionList(collect);
        return ResultUtils.success(userPaperQuestionVo);
    }

    private void disruptionQuestion(List<QuestionVO> records, List<QuestionVO> questionVOArrayList) {
        List<QuestionVO> radioList = records.stream().filter(questionVO -> questionVO.getType().equals(QuestionTypeEnum.RADIO.getValue())).collect(Collectors.toList());
        List<QuestionVO> judgeList = records.stream().filter(questionVO -> questionVO.getType().equals(QuestionTypeEnum.JUDGE.getValue())).collect(Collectors.toList());
        List<QuestionVO> multiList = records.stream().filter(questionVO -> questionVO.getType().equals(QuestionTypeEnum.MULTI.getValue())).collect(Collectors.toList());
        List<QuestionVO> subjectiveList = records.stream().filter(questionVO -> questionVO.getType().equals(QuestionTypeEnum.SUBJECTIVE.getValue())).collect(Collectors.toList());
        Collections.shuffle(radioList);
        Collections.shuffle(judgeList);
        Collections.shuffle(multiList);
        Collections.shuffle(subjectiveList);
        questionVOArrayList.addAll(radioList);
        questionVOArrayList.addAll(judgeList);
        questionVOArrayList.addAll(multiList);
        questionVOArrayList.addAll(subjectiveList);
    }

    // endregion
}
